﻿namespace NTLib.Core.Extensions
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    /// <summary>
    /// 
    /// </summary>
    public static class IEnumerableExtensions
    {
        #region Methods

        /// <summary>
        /// Clear the collection pass in argument and dispose all the element inside is it's of type <see cref="IDisposable" />
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection">The collection.</param>
        /// <param name="errorHandler">The error handler.</param>
        public static void SafeClear<T>(this Queue<T> collection, Action<T, Exception> errorHandler = null)
        {
            var tmp = collection.ToList();
            tmp.SafeClear(errorHandler);
            collection.Clear();
        }

        /// <summary>
        /// Clear the collection pass in argument and dispose all the element inside is it's of type <see cref="IDisposable" />
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection">The collection.</param>
        /// <param name="errorHandler">The error handler.</param>
        public static void SafeClear<T>(this Stack<T> collection, Action<T, Exception> errorHandler = null)
        {
            var tmp = collection.ToList();
            tmp.SafeClear(errorHandler);
            collection.Clear();
        }

        /// <summary>
        /// Clear the collection pass in argument and dispose all the element inside is it's of type <see cref="IDisposable" />
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="collection">The collection.</param>
        /// <param name="errorHandler">The error handler.</param>
        public static void SafeClear<T>(this ICollection<T> collection, Action<T, Exception> errorHandler = null)
        {
            var tmp = collection.ToArray();
            foreach (T t in tmp)
            {
                try
                {
                    if (t is IDisposable)
                        ((IDisposable)t).Dispose();
                }
                catch (Exception ex)
                {
                    if (errorHandler != null)
                    {
                        try
                        {
                            errorHandler(t, ex);
                        }
                        catch
                        {

                        }
                    }
                }
            }

            collection.Clear();
        }

        /// <summary>
        /// Clear the dictionary pass in argument and dispose all the element inside is it's of type <see cref="IDisposable" />
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="U"></typeparam>
        /// <param name="collection">The collection.</param>
        /// <param name="errorHandler">The error handler.</param>
        public static void SafeClear<T, U>(this IDictionary<T, U> collection, Action<KeyValuePair<T, U>, Exception> errorHandler = null)
        {
            var tmp = collection.ToArray();
            foreach (var t in tmp)
            {
                try
                {
                    if (t.Key is IDisposable)
                        ((IDisposable)t.Key).Dispose();

                    if (t.Value != null && t.Value is IDisposable)
                        ((IDisposable)t.Value).Dispose();
                }
                catch (Exception ex)
                {
                    if (errorHandler != null)
                    {
                        try
                        {
                            errorHandler(t, ex);
                        }
                        catch
                        {

                        }
                    }
                }
            }

            collection.Clear();
        }

        #endregion
    }
}
